﻿package com.pandemicode.framework.controls {
	import com.pandemicode.framework.interfaces.IDisposeable;
	import flash.utils.getTimer;
    import flash.events.Event;
    import flash.display.Sprite;
    import flash.text.TextField;
	import org.osflash.signals.natives.NativeSignal;
	import org.osflash.signals.Signal;
	
	/**
	* @author Michael Lawrence
	* @version 1.0.0
	*/
	public class FrameRate extends DefaultTextField implements IDisposeable {
		private var _time:int;
        private var _prevTime:int = 0;
        private var _fps:int;
		
		private var _addedToStage:NativeSignal;
		private var _removedFromStage:NativeSignal;
		private var _enterFrame:NativeSignal;
		private var _changed:Signal;
		
		public function get changed():Signal { return this._changed; }
		
		/**
		 * A textfield that displays the current frame rate.
		 */
		public function FrameRate() {
			super(20, 0xffff00);
			
			this._addedToStage = new NativeSignal(this, Event.ADDED_TO_STAGE, Event);
			this._removedFromStage = new NativeSignal(this, Event.REMOVED_FROM_STAGE, Event);
			this._enterFrame = new NativeSignal(this, Event.ENTER_FRAME, Event);
			
			if (this.stage == null) this._addedToStage.add(this.init);
			else this.init();
			this._removedFromStage.add(this._dispose);
		}
		
		/**
		 * Initiallizes the frame rate tracker.
		 * @param	e	The dispatched event.
		 */
		private function init(e:Event = null):void {
			this._addedToStage.remove(this.init);
			this._enterFrame.add(this.onEnterFrame);
		}
		
		/**
		 * Occurs every frame and updates the display.
		 * @param	e	The dispatched event.
		 */
		private function onEnterFrame(e:Event):void {
			this._time = getTimer();
			if(this._time != this._prevTime) {
				this._fps = 1000 / (this._time - this._prevTime);
				this._prevTime = getTimer();
				this.text = "fps: " + this._fps;
				this._changed.dispatch();
			}
        }
		
		/**
		 * Disposes of the current object.
		 */
		public function dispose():void {
			this._addedToStage.removeAll();
			this._removedFromStage.removeAll();
			this._enterFrame.removeAll();
			this._changed.removeAll();
		}
		
		/**
		 * Disposes of the current object.
		 * @param	e	The dispatched event.
		 */
		private function _dispose(e:Event = null):void {
			this.dispose();
		}
	}
}
